package TestPaperSystem.controller;

import TestPaperSystem.Dto.UserLoginDto;
import TestPaperSystem.Dto.WebSocketDTO;
import TestPaperSystem.config.MyWebSocketConf;
import TestPaperSystem.utils.RedisUtils;
import TestPaperSystem.utils.ResponseUtils_R;
import javafx.beans.binding.ObjectExpression;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Component
@ServerEndpoint(value = "/ws/{examId}/{sendId}" ,configurator = MyWebSocketConf.class,encoders = {ResponseUtils_R.class})
public class WebSocket {

    private static Map<String, Set<Session>> exams = new ConcurrentHashMap<>();

    private static Map<String , Session> user = new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(@PathParam("examId") String examId  , @PathParam("sendId") String sendId, Session session) throws IOException, EncodeException {

        if(!exams.containsKey(examId)){
            Set<Session> room = new HashSet<>();
            room.add(session);
            exams.put(examId,room);
        }else{
            exams.get(examId).add(session);
        }
        if(!user.containsKey(sendId))
            //上线人数纪录
            user.put(sendId,session);

        final String token = (String) session.getUserProperties().get("token");
        UserLoginDto dto = (UserLoginDto) RedisUtils.redis.opsForValue().get(token);
        if(dto != null){
            this.broadCast(examId,dto.getRealName(),sendId,dto.getRealName()+"上线了",false ,session);
            this.addRoomOtherUser(examId ,session);
        }

    }
    @OnClose
    public void onClose(@PathParam("examId") String examId,@PathParam("sendId") String sendId , Session session){
        try{
            exams.get(examId).remove(session);
            final String token = (String) session.getUserProperties().get("token");

            if(exams.containsKey(examId)){
                UserLoginDto dto = (UserLoginDto) RedisUtils.redis.opsForValue().get(token);

                if(dto != null)
                    this.broadCast(examId , dto.getRealName() , sendId ,
                            dto.getRealName() +"关闭摄像头" , true ,session);
            }
            if(user.containsKey(sendId))
                user.remove(sendId);
        }catch (Exception e){
            e.printStackTrace();
        }



    }

    @OnMessage
    public void onMessage( @PathParam("examId") String examId , @PathParam("sendId") String sendId , Session session, String imgUrl){
        try{
            final String token = (String) session.getUserProperties().get("token");

            UserLoginDto dto = (UserLoginDto) RedisUtils.redis.opsForValue().get(token);

            if(dto != null)
                this.broadCast(examId , dto.getRealName() , sendId , imgUrl , false ,session);

        }catch  (Exception e){
            e.printStackTrace();
        }

    }

    @OnError
    public void onError(Session session , Throwable err){
        System.out.println("Error");
        err.printStackTrace();
    }



    public synchronized void broadCast(String examId, String sendName ,
                                       String sendId ,String msg , Boolean isClose , Session session){
        WebSocketDTO dto = new WebSocketDTO();
        exams.get(examId).forEach(s ->{
            if(s != null && !s.getId().equals(session.getId())) {
                try {
                    dto.setImgUrl(msg);
                    dto.setUserId(sendId);
                    dto.setRealName(sendName);
                    s.getBasicRemote().sendObject(isClose ? ResponseUtils_R.error(dto) : ResponseUtils_R.success(dto));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public synchronized void addRoomOtherUser(String examId, Session session) throws IOException, EncodeException {
        List<String> users = new ArrayList<>();
        exams.get(examId).forEach(s ->{
            if(s != null && !s.getId().equals(session.getId())){
                final String token = (String) s.getUserProperties().get("token");

                UserLoginDto dto = (UserLoginDto) RedisUtils.redis.opsForValue().get(token);
                if(dto != null)
                    users.add(dto.getRealName());
            }

        });

        if(users.isEmpty()){
            return;
        }

        Map<String , Object> map = new HashMap<>();
        map.put("users",users);
        map.put("flag","-1");
        session.getBasicRemote().sendObject(ResponseUtils_R.success(map));
    }
}
